package com.nodecollege.cloud.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.nodecollege.cloud.common.constants.NCConstants;
import com.nodecollege.cloud.common.enums.UpmsErrEnum;
import com.nodecollege.cloud.common.exception.UpmsException;
import com.nodecollege.cloud.common.model.NCResult;
import com.nodecollege.cloud.common.model.QueryVO;
import com.nodecollege.cloud.common.model.po.UpmsAdmin;
import com.nodecollege.cloud.common.model.po.UpmsAdminPassword;
import com.nodecollege.cloud.common.model.vo.LoginVO;
import com.nodecollege.cloud.common.utils.NCUtils;
import com.nodecollege.cloud.common.utils.RegularExpUtils;
import com.nodecollege.cloud.core.utils.PasswordUtil;
import com.nodecollege.cloud.dao.mapper.UpmsAdminMapper;
import com.nodecollege.cloud.dao.mapper.UpmsAdminPasswordMapper;
import com.nodecollege.cloud.service.AdminService;
import com.nodecollege.cloud.service.PasswordPolicyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 管理员service
 *
 * @author LC
 * @date 2019/11/27 19:36
 */
@Service
public class AdminServiceImpl implements AdminService {

    @Autowired
    private UpmsAdminMapper upmsAdminMapper;

    @Autowired
    private UpmsAdminPasswordMapper upmsAdminPasswordMapper;

    @Autowired
    private PasswordPolicyService passwordPolicyService;

    /**
     * 查询管理员列表
     *
     * @param query
     */
    @Override
    public NCResult<UpmsAdmin> getAdminList(QueryVO<UpmsAdmin> query) {
        List<UpmsAdmin> list = new ArrayList<>();
        Long total = 0L;
        if (NCConstants.INT_NEGATIVE_1.equals(query.getPageSize())) {
            list = upmsAdminMapper.selectAdminListByMap(query.toMap());
            total = NCUtils.isNullOrEmpty(list) ? 0 : Long.parseLong(list.size() + "");
        } else {
            Page page = PageHelper.startPage(query.getPageNum(), query.getPageSize());
            if (query.isSort()) {
                page.setOrderBy(query.getSortKey() + " " + query.getSortDirection());
            }
            list = upmsAdminMapper.selectAdminListByMap(query.toMap());
            total = page.getTotal();
        }
        return NCResult.ok(list, total);
    }

    /**
     * 新增管理员
     *
     * @param loginVO
     */
    @Override
    public UpmsAdmin addAdmin(LoginVO loginVO) {
        // 0 必填信息校验
        NCUtils.nullOrEmptyThrow(loginVO.getAccount(), new UpmsException(UpmsErrEnum.ADMIN_ACCOUNT_NULL_ERROR));
        // todo 查询配置文件获取 默认密码
        if (NCConstants.INT_1.equals(loginVO.getSource())) {
            loginVO.setPassword("123456");
        }

        NCUtils.nullOrEmptyThrow(loginVO.getAccount(), new UpmsException("-1", "管理员密码不能为空！"));
        NCUtils.nullOrEmptyThrow(loginVO.getTelephone(), new UpmsException("-1", "管理员电话不能为空！"));
        if (!RegularExpUtils.checkTelephone(loginVO.getTelephone())) {
            throw new UpmsException("-1", "电话格式不正确！");
        }

        // 1 账号是否重复校验
        UpmsAdmin admin = new UpmsAdmin();
        admin.setAccount(loginVO.getAccount());
        List<UpmsAdmin> result = upmsAdminMapper.selectAdminListByMap(new QueryVO<>(admin).toMap());
        if (!result.isEmpty()) {
            throw new UpmsException("-1", "当前账号已注册！");
        }

        // 2 手机号是否重复校验
        admin.setAccount(null);
        admin.setTelephone(loginVO.getTelephone());
        result = upmsAdminMapper.selectAdminListByMap(new QueryVO<>(admin).toMap());
        if (!result.isEmpty()) {
            throw new UpmsException("-1", "当前手机号已注册！");
        }
        // 3 保存数据
        admin.setAccount(loginVO.getAccount());
        admin.setCreateTime(new Date());
        admin.setState(1);
        // 管理员添加用户 首次登陆设为true
        admin.setFirstLogin(NCConstants.INT_1.equals(loginVO.getSource()));
        upmsAdminMapper.insertSelective(admin);

        // 查出新增管理员id
        List<UpmsAdmin> result2 = upmsAdminMapper.selectAdminListByMap(new QueryVO<>(admin).toMap());

        String salt = PasswordUtil.getRandomSalt();
        String password = PasswordUtil.md5(loginVO.getPassword(), salt);

        UpmsAdminPassword upmsAdminPassword = new UpmsAdminPassword();
        upmsAdminPassword.setAdminId(result2.get(0).getAdminId());
        upmsAdminPassword.setPassword(password);
        upmsAdminPassword.setSalt(salt);
        upmsAdminPassword.setCreateTime(new Date());
        upmsAdminPasswordMapper.insertSelective(upmsAdminPassword);

        // 清除登录失败次数缓存
        passwordPolicyService.deleteLoginFileNum(admin.getAccount());
        return admin;
    }

    /**
     * 修改管理员
     *
     * @param upmsAdmin
     */
    @Override
    public void updateAdmin(UpmsAdmin upmsAdmin) {
        UpmsAdmin exit = upmsAdminMapper.selectByPrimaryKey(upmsAdmin.getAdminId());

        NCUtils.nullOrEmptyThrow(exit, new UpmsException("-1", "修改管理员失败，无此用户！"));
        if (!RegularExpUtils.checkTelephone(upmsAdmin.getTelephone())) {
            throw new UpmsException("-1", "电话格式不正确！");
        }
        UpmsAdmin query = new UpmsAdmin();
        query.setTelephone(upmsAdmin.getTelephone());
        List<UpmsAdmin> result = upmsAdminMapper.selectAdminListByMap(new QueryVO<>(query).toMap());
        if (result.size() == 1 && !exit.getAdminId().equals(result.get(0).getAdminId())) {
            throw new UpmsException("", "该电话号码已存在！");
        }

        // 不能修改账号
        upmsAdmin.setAccount(null);
        // 不能修改状态
        upmsAdmin.setState(null);
        // 不能修改创建时间
        upmsAdmin.setCreateTime(null);
        upmsAdminMapper.updateByPrimaryKeySelective(upmsAdmin);
    }

    /**
     * 更新管理员密码
     *
     * @param account     管理员账号
     * @param oldPassword 旧密码
     * @param newPassword 新密码
     * @param cert        图片验证码
     */
    @Override
    public void updateAdminPassword(String account, String oldPassword, String newPassword, String cert) {
        // 登陆前校验
        passwordPolicyService.checkLoginPolicy(account, oldPassword, newPassword, cert);

        UpmsAdmin query = new UpmsAdmin();
        query.setAccount(account);
        List<UpmsAdmin> adminList = upmsAdminMapper.selectAdminListByMap(new QueryVO<>(query).toMap());

        NCUtils.nullOrEmptyThrow(adminList, new UpmsException("-1", "更新管理员密码失败！不存在该账号信息！"));

        // 根据管理员id获取密码信息
        List<UpmsAdminPassword> list = upmsAdminPasswordMapper.selectListByAdminId(adminList.get(0).getAdminId());

        // 旧密码校验
        if (!list.get(0).getPassword().equals(PasswordUtil.md5(oldPassword, list.get(0).getSalt()))) {
            Integer loginFileNum = passwordPolicyService.setLoginFileNum(account);
            throw new UpmsException("-1", MessageFormat.format("旧密码输入错误，请重新输入！(第{0}次)", loginFileNum));
        }

        // 注册密码校验
        passwordPolicyService.checkRegisterPolicy(newPassword, account);

        // 更新密码校验
        passwordPolicyService.checkUpdatePolicy(list, newPassword);

        // 更新密码
        UpmsAdminPassword password = new UpmsAdminPassword();
        password.setAdminId(adminList.get(0).getAdminId());
        password.setSalt(PasswordUtil.getRandomSalt());
        password.setPassword(PasswordUtil.md5(newPassword, password.getSalt()));
        password.setCreateTime(new Date());
        upmsAdminPasswordMapper.insertSelective(password);

        // 管理员信息设置成非首次登录
        UpmsAdmin updateAdmin = new UpmsAdmin();
        updateAdmin.setAdminId(adminList.get(0).getAdminId());
        updateAdmin.setFirstLogin(false);
        upmsAdminMapper.updateByPrimaryKeySelective(updateAdmin);

        // 清除登录失败次数缓存
        passwordPolicyService.deleteLoginFileNum(account);
    }

    /**
     * 根据账号获取管理员信息
     *
     * @param account
     */
    @Override
    public UpmsAdmin getAdminByAccount(String account) {
        UpmsAdmin admin = new UpmsAdmin();
        admin.setAccount(account);
        List<UpmsAdmin> result = upmsAdminMapper.selectAdminListByMap(new QueryVO<>(admin).toMap());

        NCUtils.nullOrEmptyThrow(result, new UpmsException("-1", "根据账号未获取到用户信息！"));

        return result.get(0);
    }

    /**
     * 删除管理员
     *
     * @param id
     */
    @Override
    public void delAdmin(Long id) {
        // 根据id查询管理员信息
        UpmsAdmin admin = upmsAdminMapper.selectByPrimaryKey(id);

        NCUtils.nullOrEmptyThrow(admin, new UpmsException("-1", "该管理员不存在！"));

        if (NCConstants.INT_0.equals(admin.getState())) {
            throw new UpmsException("-1", "该管理员不能删除");
        }
        admin.setState(NCConstants.INT_NEGATIVE_1);
        upmsAdminMapper.updateByPrimaryKeySelective(admin);
    }

    /**
     * 冻结/解冻管理员
     *
     * @param upmsAdmin
     */
    @Override
    public void lockAdmin(UpmsAdmin upmsAdmin) {
        // 根据id查询管理员信息
        UpmsAdmin admin = upmsAdminMapper.selectByPrimaryKey(upmsAdmin.getAdminId());
        NCUtils.nullOrEmptyThrow(admin, new UpmsException("-1", "该管理员不存在！"));
        if (NCConstants.INT_0.equals(admin.getState())) {
            throw new UpmsException("-1", "超级管理员不能冻结！");
        }
        if (!Arrays.asList(NCConstants.INT_1, NCConstants.INT_2).contains(upmsAdmin.getState())) {
            throw new UpmsException("", "只能进行冻结或者解冻操作");
        }
        UpmsAdmin lockAdmin = new UpmsAdmin();
        lockAdmin.setAdminId(upmsAdmin.getAdminId());
        lockAdmin.setState(upmsAdmin.getState());
        upmsAdminMapper.updateByPrimaryKeySelective(lockAdmin);
    }

    /**
     * 重置管理员密码
     * @param admin
     */
    @Override
    public void resetPwd(UpmsAdmin admin) {
        // 根据id查询管理员信息
        UpmsAdmin ex = upmsAdminMapper.selectByPrimaryKey(admin.getAdminId());
        NCUtils.nullOrEmptyThrow(ex, new UpmsException("-1", "该管理员不存在！"));
        if (NCConstants.INT_0.equals(admin.getState())) {
            throw new UpmsException("-1", "超级管理员不能重置密码！");
        }
        // 更新密码
        UpmsAdminPassword password = new UpmsAdminPassword();
        password.setAdminId(ex.getAdminId());
        password.setSalt(PasswordUtil.getRandomSalt());
        password.setPassword(PasswordUtil.md5("123456", password.getSalt()));
        password.setCreateTime(new Date());
        upmsAdminPasswordMapper.insertSelective(password);

        // 管理员信息设置成非首次登录
        UpmsAdmin updateAdmin = new UpmsAdmin();
        updateAdmin.setAdminId(admin.getAdminId());
        updateAdmin.setFirstLogin(true);
        upmsAdminMapper.updateByPrimaryKeySelective(updateAdmin);
    }
}
